home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / p063b9s.zip / UNIT / ZSEND.PAS < prev   
Pascal/Delphi Source File  |  1997-03-02  |  20KB  |  695 lines

  1. UNIT ZSend;
  2. {╔══════════════════════════════════════════════════════════════════════════╗}
  3. {║ ZModem send routine                           Last changed: 02.03.97  SA ║}
  4. {║                                                                          ║}
  5. {║                         (C) Copyright 1989-97 by                         ║}
  6. {║       Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager        ║}
  7. {║                                                                          ║}
  8. {║ This source may not be given to anybody, without the written permission  ║}
  9. {║ from The Portal Team.                                                    ║}
  10. {╚══════════════════════════════════════════════════════════════════════════╝}
  11. {$I POPDEFS.INC}
  12.  
  13. INTERFACE
  14.  
  15. USES Use32, Dos;
  16.  
  17. FUNCTION ZModemSend(CONST FName, Alias: PathStr; FSent: Integer; WaZoo: Word): Integer;
  18.  
  19. IMPLEMENTATION
  20.  
  21. USES OpCrt, OpDate, OpRoot, OpString, ApTimer,
  22.      PoPTypes, Globals, Crc, Com, UnixDate, ZMisc, TransVid, Util, MTask,
  23.      LogFile;
  24.  
  25.  
  26. FUNCTION ZModemSend;
  27. LABEL
  28.   Done, Err_Out;
  29.  
  30. VAR
  31.   CanDo32        : Boolean;
  32.   FileName, p, s : PathStr;
  33.   FSize          : String[10];
  34.   MaxBlkLen,
  35.   RxBufLen,
  36.   Zsize, rc      : Word;
  37.   Dt             : DateTime;
  38.   Srec           : SEARCHREC;
  39.   LastSent       : Byte;
  40.   OutFile        : FILE;
  41.   RxFlags,
  42.   ZRPosCount     : Integer;
  43.   LastZRpos,
  44.   StrtPos,
  45.   udate, TxPos   : LongInt;
  46.   TxBuf          : POINTER;
  47.  
  48. {
  49.   PROCEDURE ZSSendBuffer;
  50.   BEGIN
  51.     FSendBlock(TxFosBuf^, TxFosPos);
  52.     TxFosPos:=0;
  53.   END;
  54. }
  55.  
  56.   PROCEDURE ZSSendByte(c: Byte);
  57.   BEGIN
  58.     IF ((c AND $7f) IN [16, 17, 19, 24]) OR (((c AND $7f)=13) AND ((LastSent AND $7f)=64)) THEN
  59.     BEGIN
  60.       ComPort^.WriteByte(ZDLE, False);
  61.       LastSent:=c XOR 64;
  62.     END ELSE
  63.       LastSent:=c;
  64.     ComPort^.WriteByte(LastSent, False);
  65.   END;
  66.  
  67. {
  68.   PROCEDURE ZSSendRawByte(c: Byte);
  69.   BEGIN
  70.     BT0(TxFosBuf^)[TxFosPos]:=c;
  71.     Inc(TxFosPos);
  72.   END;
  73. }
  74. (*  PROCEDURE ZSSendByte(b: Byte); External;
  75.   {$L send} *)
  76.  
  77.   PROCEDURE ZS32SendBinaryHeader(HdrType: Integer; CONST Hdr: HeaderType);
  78.   VAR
  79.     Crc            : LongInt;
  80.     n              : Byte;
  81.   BEGIN
  82. {$IFDEF ZDebug}
  83.     AddLog('!','ZS32SendBinaryHeader');
  84. {$ENDIF}
  85.     ComPort^.WriteByte(ZBIN32, False);
  86.     ZSSendByte(Byte(HdrType));
  87.     Crc:=$ffffffff;
  88.     Crc:=UpdCrc32(HdrType, Crc);
  89.     FOR n:=0 TO 3 DO
  90.     BEGIN
  91.       ZSSendByte(Hdr[n]);
  92.       Crc:=UpdCrc32(Hdr[n], Crc);
  93.     END;
  94.     Crc := NOT Crc;
  95.     FOR n := 0 TO 3 DO
  96.     BEGIN
  97.       ZSSendByte(Byte(Crc));
  98.       Crc := Crc SHR 8;
  99.     END;
  100.   END;
  101.  
  102.   PROCEDURE ZSSendBinaryHeader(HdrType: Integer; CONST Hdr: HeaderType);
  103.   VAR
  104.     Crc : Word;
  105.     n   : Byte;
  106.     t   : EventTimer;
  107.   BEGIN
  108. {$IFDEF ZDebug}
  109.     AddLog('!','ZSSendBinaryHeader');
  110. {$ENDIF}
  111.     LastSent:=0;
  112.     ComPort^.WriteByte(ZPAD, False);
  113.     ComPort^.WriteByte(ZDLE, False);
  114.     IF CanDo32 THEN
  115.       ZS32SendBinaryHeader(HdrType, Hdr)
  116.     ELSE
  117.     BEGIN
  118.       ComPort^.WriteByte(ZBIN, False);
  119.       ZSSendByte(Byte(HdrType));
  120.       Crc:=UpdCrc16(Byte(HdrType), 0);
  121.       FOR n:=0 TO 3 DO
  122.       BEGIN
  123.         ZSSendByte(Hdr[n]);
  124.         Crc:=UpdCrc16(Hdr[n], Crc);
  125.       END;
  126.       Crc:=UpdCrc16(0, Crc);
  127.       Crc:=UpdCrc16(0, Crc);
  128.       ZSSendByte(Hi(Crc));
  129.       ZSSendByte(Lo(Crc));
  130.     END;
  131.     ComPort^.FlushTx;
  132.     IF HdrType<>ZDATA THEN
  133.     BEGIN
  134.       NewTimerSecs(t, 2);
  135.       WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) And (Not TimerExpired(t)) DO
  136. {        GiveUpTime};
  137.       IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
  138.     END;
  139.   END;
  140.  
  141.   FUNCTION ZSSyncWithReceiver(NumErrs: Integer): Integer;
  142.   VAR
  143.     c              : Integer;
  144.   BEGIN
  145. {$IFDEF BoDebug}
  146.     AddLog('!','ZSSyncWithReceiver');
  147. {$ENDIF}
  148.     ZSSyncWithReceiver := Error;
  149.     REPEAT
  150.       c := ZGetHeader(RxHdr);
  151.       ComPort^.PurgeIn;
  152.       CASE c OF
  153.         TimeOut : BEGIN
  154.                     ShowError('Timeout',True,false,false);
  155.                     Dec(NumErrs);
  156.                     IF NumErrs < 0 THEN Exit;
  157.                   END;
  158.         ZCAN,
  159.         ZABORT,
  160.         ZFIN,
  161.         RCDO : BEGIN
  162.                  ShowError('No Carrier',True,false,false);
  163.                  Exit;
  164.                END;
  165.         ZRPOS : BEGIN
  166.                   IF RxPos = LastZRpos THEN
  167.                   BEGIN
  168.                     Dec(ZRPosCount);
  169.                     IF ZRPosCount < 0 THEN Exit;
  170.                   END ELSE
  171.                     ZRPosCount := 10;
  172.                   LastZRpos := RxPos;
  173.                   Seek(OutFile, RxPos);
  174.                   TxPos := RxPos;
  175.                   ShowError('Resending from '+Long2Str(TxPos),False,False,false);
  176.                   ZSSyncWithReceiver := c;
  177.                   Exit;
  178.                 END;
  179.         ZACK,
  180.         ZSKIP,
  181.         ZRINIT : BEGIN
  182. {                  IF c = ZSKIP THEN ShowError('Remote skipped file',False,False,False);}
  183.                    ZSSyncWithReceiver := c;
  184.                    Exit;
  185.                  END;
  186.       ELSE BEGIN
  187.           ShowError('Scratching head',True,false,false);
  188.           ZSSendBinaryHeader(ZNAK, TxHdr);
  189.         END;
  190.       END;
  191.     UNTIL FALSE;
  192.   END;
  193.  
  194.   PROCEDURE ZSEndSend;
  195.   BEGIN
  196. {$IFDEF ZDebug}
  197.     AddLog('!','ZSEndSend');
  198. {$ENDIF}
  199.     REPEAT
  200.       ZPutLongIntoHeader(0, TxHdr);
  201.       ZSSendBinaryHeader(ZFIN, TxHdr);
  202.       CASE ZGetHeader(RxHdr) OF
  203.         ZFIN : BEGIN
  204.                  ShowError('Transfer completed',False,false,false);
  205.                  ComPort^.WriteByte(Byte('O'), False);
  206.                  ComPort^.WriteByte(Byte('O'), True);
  207.                  WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) DO
  208.                    GiveUpTime;
  209.                  IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
  210.                  Exit;
  211.                END;
  212.         ZCAN,
  213.         RCDO,
  214.         TimeOut : Exit;
  215.       END;
  216.     UNTIL FALSE;
  217.   END;
  218.  
  219.   PROCEDURE ZS32SendData(Buf: Pointer; Len: Word; FrameEnd: Integer);
  220.   VAR
  221.     Crc            : LongInt;
  222.     n              : Word;
  223.   BEGIN
  224. {$IFDEF ZDebug}
  225.     AddLog('!','ZS32SendData');
  226. {$ENDIF}
  227.     Crc := $ffffffff;
  228.     IF Len>0 THEN
  229.     BEGIN
  230.       FOR n:=0 TO len-1 DO
  231.       BEGIN
  232.         ZSSendByte(BufAry(Buf^)[n]);
  233.         Crc := UpdCrc32(BufAry(Buf^)[n], Crc);
  234.       END;
  235.     END;
  236.     Crc := UpdCrc32(FrameEnd, Crc);
  237.     Crc := NOT Crc;
  238.     ComPort^.WriteByte(ZDLE, False);
  239.     ComPort^.WriteByte(Byte(FrameEnd), False);
  240.     FOR n:=1 TO 4 DO
  241.     BEGIN
  242.       ZSSendByte(Byte(Crc));
  243.       Crc:=Crc SHR 8;
  244.     END;
  245. {$IFDEF ZDebug}
  246.     AddLog('!','END ZS32SendData');
  247. {$ENDIF}
  248.   END;
  249.  
  250.   PROCEDURE ZSSendData(Buf: Pointer; Len: Word; FrameEnd: Integer);
  251.   VAR
  252.     Crc : Word;
  253.     n   : Word;
  254.     t   : EventTimer;
  255.   BEGIN
  256. {$IFDEF ZDebug}
  257.     AddLog('!','ZSSendData');
  258. {$ENDIF}
  259.     IF CanDo32 THEN
  260.       ZS32SendData(buf, len, FrameEnd)
  261.     ELSE
  262.     BEGIN
  263.       Crc := 0;
  264.       IF Len>0 THEN
  265.       BEGIN
  266.         FOR n:=0 TO len-1 DO
  267.         BEGIN
  268.           ZSSendByte(BufAry(Buf^)[n]);
  269.           Crc:=UpdCrc16(BufAry(Buf^)[n], Crc);
  270.         END;
  271.       END;
  272.       ComPort^.WriteByte(ZDLE, False);
  273.       ComPort^.WriteByte(Byte(FrameEnd), False);
  274.       Crc:=UpdCrc16(FrameEnd, Crc);
  275.       Crc:=UpdCrc16(0, Crc);
  276.       Crc:=UpdCrc16(0, Crc);
  277.       ZSSendByte(Hi(Crc));
  278.       ZSSendByte(Lo(Crc));
  279.     END;
  280.     ComPort^.FlushTx;
  281.     IF FrameEnd = ZCRCW THEN
  282.     BEGIN
  283.       ComPort^.WriteByte(XON, True);
  284.       NewTimerSecs(t, 2);
  285.       WHILE (ComPort^.Carrier) AND (NOT ComPort^.OutEmpty) And (Not TimerExpired(t)) DO
  286. {        GiveUpTime};
  287.       IF NOT ComPort^.Carrier THEN ComPort^.PurgeOut;
  288.     END;
  289. {$IFDEF ZDebug}
  290.     AddLog('!','ZSSendData');
  291. {$ENDIF}
  292.   END;
  293.  
  294.   FUNCTION ZSGetReceiverInfo: Integer;
  295.   VAR
  296.     n              : Byte;
  297.   BEGIN
  298. {$IFDEF ZDebug}
  299.     AddLog('!','ZSGetReceiverInfo');
  300. {$ENDIF}
  301.     FOR n := 0 TO 9 DO
  302.     BEGIN
  303.       CASE ZGetHeader(RxHdr) OF
  304.         ZCHALLENGE : BEGIN
  305.                        ZPutLongIntoHeader(RxPos, TxHdr);
  306.                        ZSendHexHeader(ZACK, TxHdr);
  307.                        Continue;
  308.                      END;
  309.         ZCOMMAND : BEGIN
  310.                      ZPutLongIntoHeader(0, TxHdr);
  311.                      ZSendHexHeader(ZRQINIT, TxHdr);
  312.                      Continue;
  313.                    END;
  314.         ZRINIT : BEGIN
  315.                    RxFlags := 255 AND RxHdr[ZF0];
  316.                    RxBufLen := (Word(RxHdr[ZP1] SHR 8)) + RxHdr[ZP0];
  317.                    CanDo32 := (RxFlags AND CANFC32) = CANFC32;
  318.                    IF CanDo32 THEN ShowErrorCheckingMethod('Z-Send CRC32',false) ELSE
  319.                      ShowErrorCheckingMethod('Z-Send CRC16',false);
  320.                    ZSGetReceiverInfo := ok;
  321.                    Exit;
  322.                  END;
  323.         ZCAN,
  324.         RCDO,
  325.         TimeOut : BEGIN
  326.                     ShowError('TIMEOUT',True,false,false);
  327.                     ZSGetReceiverInfo := Error;
  328.                     Exit;
  329.                   END;
  330.         ZRQINIT : IF RxHdr[ZF0] = ZCOMMAND THEN Continue;
  331.       ELSE ZSendHexHeader(ZNAK, TxHdr);
  332.       END;
  333.     END;
  334.     ZSGetReceiverInfo := Error;
  335.   END;
  336.  
  337.   FUNCTION ZSSendFileData(WaZoo: Integer) : Integer;
  338.   LABEL
  339.     Oops, SomeMore, WaitAck;
  340.   VAR
  341.     c, e, newcnt   : Integer;
  342.     BlkLen, MaxBlkLen, GoodBlks, GoodNeeded : Word;
  343.     t              : EventTimer;
  344.   BEGIN
  345. {$IFDEF ZDebug}
  346.     AddLog('!','ZSSendFileData');
  347. {$ENDIF}
  348.     newcnt := 1; GoodBlks := 0; GoodNeeded := 1;
  349.     IF (ComPort^.GetBaudRate>=0) And (ComPort^.GetBaudRate<300) THEN
  350.       MaxBlkLen:=128
  351.     ELSE
  352.       MaxBlkLen:=ComPort^.GetBaudRate Div 300 * 256;
  353.     IF MaxBlkLen>WaZooMax THEN maxBlkLen:=WaZooMax;
  354.     IF (WaZoo=0) And (MaxBlkLen>KSize) THEN MaxBlkLen:=KSize;
  355.     IF (RxBufLen <> 0) AND (MaxBlkLen > RxBufLen) THEN
  356.       MaxBlkLen := RxBufLen;
  357.     BlkLen := MaxBlkLen;
  358. SomeMore:
  359. {$IFDEF ZDebug}
  360.     AddLog('!','L01');
  361. {$ENDIF}
  362.     IF ComPort^.Keypressed THEN
  363.     BEGIN
  364. WaitAck:
  365. {$IFDEF ZDebug}
  366.     AddLog('!','L02');
  367. {$ENDIF}
  368.       c := ZSSyncWithReceiver(1);
  369.       CASE c OF
  370.         ZSKIP : BEGIN
  371.                   ShowError('Remote skipped file',False,False,false);
  372.                   ZSSendFileData := c;
  373.                   Exit;
  374.                 END;
  375.         ZACK  : ;
  376.         ZRPOS : BEGIN
  377.                   IF BlkLen>128 THEN BlkLen:=BlkLen SHR 2 ELSE BlkLen:=64;
  378.                   GoodBlks := 0;
  379.                   IF (GoodNeeded SHL 1) > 8 THEN
  380.                     GoodNeeded := 8
  381.                   ELSE
  382.                     GoodNeeded := GoodNeeded SHL 1;
  383.                 END;
  384.         ZRINIT : BEGIN
  385.                    ZSSendFileData := ok;
  386.                    Exit;
  387.                  END;
  388.        TimeOut : ;
  389.         ELSE BEGIN
  390.                ShowError('Transfer cancelled',False,true,false);
  391.                ZSSendFileData := Error;
  392.                Exit;
  393.              END;
  394.       END;
  395.  
  396.       ZUnCorkTransmitter;
  397.       ComPort^.WriteByte(XON, True);
  398.       WHILE ComPort^.Keypressed DO
  399.       BEGIN
  400.         CASE ZTimedRead OF
  401.           Can,
  402.           RCDO,
  403.           ZPAD : GOTO WaitAck;
  404.         END;
  405.       END;
  406.     END;
  407.  
  408.     newcnt := RxBufLen;
  409.     ZPutLongIntoHeader(TxPos, TxHdr);
  410.     ZSSendBinaryHeader(ZDATA, TxHdr);
  411.  
  412.     REPEAT
  413.       IF GotESC THEN
  414.       BEGIN
  415.         ComPort^.PurgeOut;
  416.         ComPort^.SetXOn(Off);
  417.         ZSendCan;
  418.         NewTimerSecs(t, 2);
  419.         WHILE (NOT TimerExpired(t)) AND (NOT ComPort^.OutEmpty) AND (ComPort^.Carrier) DO
  420.           GiveUpTime;
  421.         ComPort^.SetXOn(On);
  422.         ShowError('Keybord ESC',False,true,false);
  423.         GOTO Oops;
  424.       END;
  425.       IF NOT ComPort^.Carrier THEN GOTO Oops;
  426.       BlockRead(OutFile, TxBuf^, BlkLen, c);
  427.       ShowBlockSize(c, False);
  428.       IF c <> Zsize THEN Zsize := c;
  429.       IF c<BlkLen THEN
  430.       BEGIN
  431.         e:=ZCRCE
  432.       END ELSE
  433.       BEGIN
  434.         newcnt:=newcnt-c;
  435.         IF (RxBufLen<>0) AND (newcnt<=0) THEN e:=ZCRCW ELSE e:=ZCRCG;
  436.       END;
  437.       ZSSendData(TxBuf, c, e);
  438.       Inc(TxPos, c);
  439.       ShowCurrentByte(TxPos,false);
  440.       Inc(GoodBlks);
  441.       IF (BlkLen < MaxBlkLen) AND (GoodBlks > GoodNeeded) THEN
  442.       BEGIN
  443.         IF (BlkLen SHL 1) < MaxBlkLen THEN
  444.           BlkLen := BlkLen SHL 1
  445.         ELSE
  446.           BlkLen := MaxBlkLen;
  447.         GoodBlks := 0;
  448.       END;
  449.       IF NOT ComPort^.Carrier THEN GOTO Oops;
  450.       IF e = ZCRCW THEN GOTO WaitAck;
  451.       WHILE ComPort^.Keypressed DO
  452.       BEGIN
  453.         CASE ZTimedRead OF
  454.           Can,
  455.           RCDO,
  456.           ZPAD : BEGIN
  457.                    ShowError('Trouble?',True,false,false);
  458.                    ComPort^.PurgeOut;
  459.                    ZSSendData(TxBuf, 0, ZCRCE);
  460.                    GOTO WaitAck;
  461.                  END;
  462.         END;
  463.       END;
  464.     UNTIL (e <> ZCRCG);
  465.  
  466.     REPEAT
  467.       ZPutLongIntoHeader(TxPos, TxHdr);
  468.       ZSSendBinaryHeader(ZEOF, TxHdr);
  469.       CASE ZSSyncWithReceiver(7) OF
  470.         ZACK : Continue;
  471.         ZRPOS : GOTO SomeMore;
  472.         ZRINIT : BEGIN
  473.                    ZSSendFileData := ok;
  474.                    Exit;
  475.                  END;
  476.         ZSKIP : BEGIN
  477.                   ShowError('Remote skipped file',False,true,false);
  478.                   ZSSendFileData := c;
  479.                   Exit;
  480.                 END;
  481.         ELSE BEGIN
  482. Oops:
  483.                ShowError('Transfer cancelled',False,true,false);
  484.                Break;
  485.              END;
  486.       END;
  487.     UNTIL FALSE;
  488.     ZSSendFileData := Error;
  489.   END;
  490.  
  491.   FUNCTION ZSSendFile(BLen, WaZoo: Word): Integer;
  492.   LABEL
  493.     Again;
  494.   VAR
  495.     t : EventTimer;
  496.     c : Integer;
  497.   BEGIN
  498. {$IFDEF ZDebug}
  499.     AddLog('!','ZSSendFile');
  500. {$ENDIF}
  501.     ZSSendFile := Error;
  502.     REPEAT
  503.       IF GotESC THEN
  504.       BEGIN
  505.         ComPort^.PurgeOut;
  506.         ComPort^.SetXOn(Off);
  507.         ZSendCan;
  508.         NewTimerSecs(t, 2);
  509.         WHILE (NOT TimerExpired(t)) AND (NOT ComPort^.OutEmpty) AND (ComPort^.Carrier) DO
  510.           GiveupTime;
  511.         ComPort^.SetXOn(On);
  512.         ShowError('Keyboard ESC',False,true,false);
  513.         Exit;
  514.       END ELSE
  515.       BEGIN
  516.         IF NOT ComPort^.Carrier THEN Break;
  517.         TxHdr[ZF0]:=LZCONV;
  518.         TxHdr[ZF1]:=LZMANAG;
  519.         TxHdr[ZF2]:=LZTRANS;
  520.         TxHdr[ZF3]:=0;
  521.         ZSSendBinaryHeader(ZFILE, TxHdr);
  522.         ZSSendData(TxBuf, BLen, ZCRCW);
  523. Again:
  524. {$IFDEF ZDebug}
  525.         AddLog('!','L03');
  526. {$ENDIF}
  527.         c := ZGetHeader(RxHdr);
  528.         CASE c OF
  529.           ZRINIT : BEGIN
  530.                      { goto again; }
  531.                      c := ZGetByte(50);
  532.                      WHILE c > 0 DO
  533.                      BEGIN
  534.                        IF c = ZPAD THEN GOTO Again;
  535.                        c:=ZGetByte(50);
  536.                      END;
  537.                      Continue;
  538.                    END;
  539.           ZCAN,
  540.           RCDO,
  541.           TimeOut,
  542.           ZFIN,
  543.           ZABORT : BEGIN
  544.                      ShowError('Transfer aborted',False,true,false);
  545.                      Break;
  546.                    END;
  547.           ZSKIP : BEGIN
  548.                     ZSSendFile := c;
  549.                     Break;
  550.                   END;
  551.           ZRPOS : BEGIN
  552.                     ShowCurrentFileName(FileName, RxPos, SRec.Size, 96, False);
  553.                     Seek(OutFile, RxPos);
  554.                     IF IoResult <> 0 THEN Break;
  555.                     ComPort^.PurgeOut;
  556.                     ComPort^.SetXOn(Off);
  557.                     ComPort^.WriteByte(XON, True);
  558.                     ComPort^.SetXOn(On);
  559.                     LastZRpos := RxPos;
  560.                     StrtPos := RxPos;
  561.                     TxPos := RxPos;
  562.                     ZRPosCount := 10;
  563.                     ComPort^.PurgeIn;
  564. {$IFDEF ZDebug}
  565.                     AddLog('!','F¥R ZSSendFileData');
  566. {$ENDIF}
  567.                     ZSSendFile := ZSSendFileData(WaZoo);
  568. {$IFDEF ZDebug}
  569.                     AddLog('!','EFTER ZSSendFileData');
  570. {$ENDIF}
  571.                     Break;
  572.                   END;
  573.           ELSE    Continue;
  574.         END;  {case}
  575.       END;  {else}
  576.     UNTIL FALSE;
  577. {$IFDEF ZDebug}
  578.     AddLog('!','END ZSSendFile');
  579. {$ENDIF}
  580.   END;
  581.  
  582.   BEGIN
  583. {$IFDEF ZDebug}
  584.     AddLog('!','ZModemSend');
  585. {$ENDIF}
  586.     ComPort^.SetBreak(Off);
  587. {    IF FCtrlC(0) THEN ;}
  588.     ComPort^.SetXon(Off); { FTransmitByte(XOn);} ComPort^.SetXOn(On);
  589.     TxBuf:=NIL; ZSize := 0;
  590.     RxBufLen:=0;
  591.     CanDo32:=FALSE;
  592.     LastSent:=0;
  593.     CASE FSent OF
  594.       0,
  595.       NOTHING_TO_DO :
  596.         BEGIN
  597.           IF FSent = 0 THEN
  598.           BEGIN
  599.             ZPutString('rz' + Char(Cr));
  600.             ZPutLongIntoHeader(LongInt(0), TxHdr);
  601.             ZSendHexHeader(ZRQINIT, TxHdr);
  602.           END;
  603.           RxTimeOut := 200;
  604.           IF ZSGetReceiverInfo = Error THEN
  605.           BEGIN
  606.             ComPort^.SetXOn(Off);
  607.             ComPort^.SetXOn(On);
  608.             ZModemSend := ZFALSE;
  609.             ShowError('Can''t get attention',True,true,false);
  610.             Exit;
  611.           END;
  612.         END;
  613.     END;
  614.     RxTimeOut := LongInt(LongInt(614400) DIV ComPort^.GetBaudRate);
  615.     IF RxTimeOut < 100 THEN RxTimeOut := 100;
  616.  
  617.     rc := ZTRUE;
  618.  
  619.     FileName := FName;
  620.     IF FName = '' THEN GOTO Done;
  621.     FINDFIRST(FileName, AnyFile, Srec);
  622.     IF DOSERROR <> 0 THEN
  623.     BEGIN
  624.       FindClose(SRec);
  625.       ComPort^.SetXOn(Off);
  626.       ComPort^.SetXOn(On);
  627.       ZModemSend:=ZTRUE;
  628.       Exit;
  629.     END;
  630.     FindClose(SRec);
  631.     { Check for TTY }
  632.     IF Alias<>'' THEN p:=Alias ELSE p:=FileName;
  633.     p:=JustFileName(p);
  634.     FSize:=Long2Str(Srec.size);
  635.     UnPackTime(SRec.Time, Dt);
  636.     WITH Dt DO
  637.       udate:=GetUnixDate(Year, Month, Day, Hour, Min, Sec);
  638.     s:=OctalL(UDate);
  639.     WHILE COPY(s,1,2)='00' DO
  640.       Delete(s,1,1);
  641.     s:=StLoCase(p)+#0+FSize+' '+s+ ' 00';
  642.     IF (ComPort^.GetBaudRate >= 0) AND (ComPort^.GetBaudRate < 300) THEN
  643.       MaxBlkLen:=128
  644.     ELSE
  645.       MaxBlkLen := ComPort^.GetBaudRate DIV 300 * 256;
  646.     IF (MaxBlkLen > WAZOOMAX) THEN MaxBlkLen := WAZOOMAX;
  647.     IF (WaZoo=0) AND (MaxBlkLen>KSIZE) THEN MaxBlkLen:=KSIZE;
  648.     IF NOT GetMemCheck(TxBuf, MaxBlkLen) THEN
  649.     BEGIN
  650.       ShowError('ZS-Not enough memory',False,True,false);
  651.       ZModemSend := Error;
  652. {      IF TxBuf<>NIL THEN FreeMem(TxBuf, MaxBlkLen);}
  653.       Exit;
  654.     END;
  655.     FillChar(TxBuf^, MaxBlkLen, 0);
  656.     Move(s[1], TxBuf^, Length(s));
  657.     Assign(OutFile, FileName); FileMode:=ShareRead+ShareDenyW;
  658.     Reset(OutFile, 1);
  659.     IF IOResult=5 THEN
  660.     BEGIN
  661.       AddLog('!','Access denied to: '+FileName);
  662.       FileName:='';
  663. {     FName:='';}
  664.       GOTO Err_Out;
  665.     END;
  666.     CASE ZSSendFile(Length(s), WaZoo) OF
  667.       Error : GOTO Err_Out;
  668.       ok : BEGIN
  669.              FileSent(FileName,'Z'+CrcStr(CanDo32),False);
  670.              GOTO Done;
  671.            END;
  672.       ZSKIP : BEGIN
  673.                 AddLog('+', 'Remote refused ' + FileName);
  674.                 rc := SPEC_COND;
  675.                 GOTO Done;
  676.               END;
  677.       ELSE GOTO Done;
  678.     END;
  679. Err_Out:
  680.     rc := ZFALSE;
  681. Done:
  682. {$IFDEF ZDebug}
  683.     AddLog('!','L04');
  684. {$ENDIF}
  685.     IF FileName<>'' THEN Close(OutFile);
  686.     IF IoResult = 0 THEN ;
  687.     IF TxBuf <> NIL THEN FreeMem(TxBuf, MaxBlkLen);
  688.     ComPort^.SetXOn(Off);
  689.     ComPort^.SetXOn(On);
  690.     IF FSent < 0 THEN ZSEndSend;
  691.     ZModemSend := rc;
  692.   END;
  693.  
  694. END.
  695.